package top.moxingwang.javawork.concurrent;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionTest {


    private volatile int signal;// 还是需要通过信号量控制abc的输出顺序

    Lock lock = new ReentrantLock(); // 只有一个锁
    Condition a = lock.newCondition();// 多个condition
    Condition b = lock.newCondition();
    Condition c = lock.newCondition();

    public void a() {// 去掉了synchronized，取而代之的是reentrantlock的lock和unlock。
        lock.lock();
        while (signal != 0) {
            try {
                a.await();// 释放cpu的执行资格和执行权，同时释放锁
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("a");
        signal++;
        b.signal();// 这里只唤醒了b
        lock.unlock();
    }

    public void b() {
        lock.lock();
        while (signal != 1) {
            try {
                b.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("b");
        signal++;
        c.signal();
        lock.unlock();
    }

    public void c() {
        lock.lock();
        while (signal != 2) {
            try {
                c.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("c");
        signal = 0;
        a.signal();
        lock.unlock();
    }

    public static void main(String[] args) {
        ConditionTest e = new ConditionTest();
        A a = new A(e);
        B b = new B(e);
        C c = new C(e);
        new Thread(a).start();
        new Thread(b).start();
        new Thread(c).start();

    }
}

class A implements Runnable {
    private ConditionTest e;

    public A(ConditionTest e) {
        this.e = e;

    }

    @Override
    public void run() {
        while (true) {
            e.a();
        }
    }
}

class B implements Runnable {
    private ConditionTest e;

    public B(ConditionTest e) {
        this.e = e;

    }

    @Override
    public void run() {
        while (true) {
            e.b();
        }
    }
}

class C implements Runnable {
    private ConditionTest e;

    public C(ConditionTest e) {
        this.e = e;

    }

    @Override
    public void run() {
        while (true) {
            e.c();
        }
    }
}